{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8009af3f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import dashscope\n",
    "\n",
    "messages = [\n",
    "{\n",
    "    \"role\": \"system\",\n",
    "    \"content\": [\n",
    "    {\"text\": \"You are a helpful assistant.\"}]\n",
    "},\n",
    "{\n",
    "    \"role\": \"user\",\n",
    "    \"content\": [\n",
    "    #{\"image\": \"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241022/emyrja/dog_and_girl.jpeg\"},\n",
    "    {\"image\": \"file://C:/Users/serap/Pictures/1.png\"},\n",
    "    {\"text\": \"图中红框处位于什么位置，有什么内容\"}]\n",
    "}]\n",
    "\n",
    "response = dashscope.MultiModalConversation.call(\n",
    "    #若没有配置环境变量， 请用百炼API Key将下行替换为： api_key =\"sk-xxx\"\n",
    "    #api_key = os.getenv('DASHSCOPE_API_KEY'),\n",
    "    api_key=\"sk-0e687ddcf0164a6fb66c1096447223c4\",  # 阿里百炼大模型API获取：https://bailian.console.aliyun.com/?apiKey=1#/api-key\n",
    "    model = 'qwen2.5-vl-32b-instruct',  # 此处以qwen-vl-max-latest为例，可按需更换模型名称。模型列表：https://help.aliyun.com/zh/model-studio/models\n",
    "    vl_high_resolution_images=True,\n",
    "    messages = messages\n",
    ")\n",
    "#print(response.output.choices[0].message.content[0][\"text\"])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "18aea54d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在图片中的红色方框部分的内容如下：\n",
      "\n",
      "### 红色圆圈内的文字：\n",
      "- **唯一规则就是：观众为王**\n",
      "  - 这句话被突出显示，并且用了一个向上的箭头指向它。\n",
      "\n",
      "---\n",
      "\n",
      "### 周围的文字（与红框相关）：\n",
      "1. 左侧上方的标题是：“剧本创作：灵光 → 数据”\n",
      "   - 表示从传统的灵感驱动转向数据驱动的方式。\n",
      "2. 中间下方的大字写着“AI重写规则的时代”，并强调了适应者生存的重要性。这句话的意思是在人工智能重塑娱乐产业的过程中，“以用户为中心”或“满足受众需求”的原则仍然是核心准则之一。\n",
      "3. 右边有三个关键词：\n",
      "   - 新赛道、投资逻辑和去中心化革命\n",
      "\n",
      "这些信息共同表明，在 AI 驱动的新时代下，虽然技术手段发生了巨大变化，但最终的核心目标依然是迎合用户的喜好和服务于市场的需求。“观众为王”这一理念仍然具有重要意义。\n",
      "\n",
      "总结来说，这个区域的重点在于说明尽管好莱坞的传统工业化公式正在被 AI 打破重组，但在新的模式之下，“用户体验至上”仍是不变的原则。这种转变体现了技术和创意结合的趋势以及对市场需求的高度关注。\n"
     ]
    }
   ],
   "source": [
    "print(response.output.choices[0].message.content[0][\"text\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "c336d8b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== JSON格式 ===\n",
      "{\n",
      "  \"status_code\": 200,\n",
      "  \"request_id\": \"2a2d8772-64d2-9550-81b9-dc225a217540\",\n",
      "  \"code\": \"\",\n",
      "  \"message\": \"\",\n",
      "  \"output\": {\n",
      "    \"text\": null,\n",
      "    \"finish_reason\": null,\n",
      "    \"choices\": [\n",
      "      {\n",
      "        \"finish_reason\": \"stop\",\n",
      "        \"message\": {\n",
      "          \"role\": \"assistant\",\n",
      "          \"content\": [\n",
      "            {\n",
      "              \"text\": \"这张图片展示了一份文件，主要内容是关于作业审批的审查意见和签字确认。以下是具体内容：\\n\\n### **五、作业单位审查意见（负责人）**\\n- 内容：同意执行。\\n- 签字人姓名：“刘均”\\n- 日期：2015年3月25日\\n\\n---\\n\\n### **六、监理单位审查意见（负责人）**\\n- 内容：同意执行。\\n- 签字人姓名：\\n- 日期：2015年3月26日\\n\\n---\\n\\n### **七、作业区域所在作业区（基层单位）审查意见**\\n- 审查意见未详细说明。\\n- 签字人姓名：“李俊”或类似签名。\\n- 日期：2015年3月28日。\\n\\n---\\n\\n### **八、二级单位业务主管部门审查意见**  \\n#### （只审批涉及一级及以上动火、三级及以上高处、二级及以上吊装作业）\\n| 部门 | 字样/信息 |\\n| --- | --- |\\n| 生产部门主管部室签字 (生产、管道工程) | \\n   - 姓名：\\\"张氏\\\" 或相似字样；\\n   - 时间戳为“20×5 年 × 月 日”。 |\\n\\n调度运行管理部门签字:\\n    * 同上, \\\" 张氏 \\\", 相同时间.\\n\\n质量安全部环保管理部分:无具体签署记录.\\n \\n\\n---\\n\\n\\n九．二級單位業務主官領導( 只審批一及以上的動火作業):\\n* 意見為 “同意”，簽名者爲張某；時間標記於「20x5」年的四月份第二天.\\n\\n\\n十 . 公司業務主管部門意見:(僅批准管線打開特等級別)\\n此處無具體記錄與說明。\\n\\n\\n\\n十一公司業務主管领导 : 貂涉管线打开特殊等级动火工作 :\\n同样没有具体的文字描述或者签章细节.\\n\\n\\n\\n保存单据由所属地级行政区负责保管一年期限内有效保留相关资料以备查验使用 。\\n\\n\\n\\n总结来说这份文档主要涵盖了不同层级对于特定施工项目的安全性评估以及最终决策过程中的各方审核与授权情况，并且明确了责任归属方及其存档要求等内容。如果需要更详细的解读，请提供进一步的信息！\"\n",
      "            }\n",
      "          ]\n",
      "        }\n",
      "      }\n",
      "    ]\n",
      "  },\n",
      "  \"usage\": {\n",
      "    \"input_tokens\": 1740,\n",
      "    \"output_tokens\": 483,\n",
      "    \"input_tokens_details\": {\n",
      "      \"text_tokens\": 23,\n",
      "      \"image_tokens\": 1717\n",
      "    },\n",
      "    \"total_tokens\": 2223,\n",
      "    \"output_tokens_details\": {\n",
      "      \"text_tokens\": 483\n",
      "    },\n",
      "    \"image_tokens\": 1717\n",
      "  }\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "print(\"\\n=== JSON格式 ===\")\n",
    "try:\n",
    "    print(json.dumps(response, indent=2, ensure_ascii=False))\n",
    "except:\n",
    "    print(\"无法转换为JSON格式\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1ea0237",
   "metadata": {},
   "source": [
    "## 计算图片需要消耗多少token\n",
    "\n",
    "每28x28像素对应一个Token，一张图最少需要4个Token。您可以通过以下代码估算图像的Token："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "910092e0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "缩放前的图像尺寸为：高度为1384，宽度为982\n",
      "缩放后的图像尺寸为：高度为1176，宽度为840\n",
      "图像的Token数为1262\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "# 使用以下命令安装Pillow库：pip install Pillow\n",
    "from PIL import Image\n",
    "\n",
    "def token_calculate(image_path):\n",
    "    # 打开指定的PNG图片文件\n",
    "    image = Image.open(image_path)\n",
    "\n",
    "    # 获取图片的原始尺寸\n",
    "    height = image.height\n",
    "    width = image.width\n",
    "    print(f\"缩放前的图像尺寸为：高度为{height}，宽度为{width}\")\n",
    "    # 将高度调整为28的整数倍\n",
    "    h_bar = round(height / 28) * 28\n",
    "    # 将宽度调整为28的整数倍\n",
    "    w_bar = round(width / 28) * 28\n",
    "    \n",
    "    # 图像的Token下限：4个Token\n",
    "    min_pixels = 28 * 28 * 4\n",
    "    # 图像的Token上限：1280个Token\n",
    "    max_pixels = 1280 * 28 * 28\n",
    "        \n",
    "    # 对图像进行缩放处理，调整像素的总数在范围[min_pixels,max_pixels]内\n",
    "    if h_bar * w_bar > max_pixels:\n",
    "        # 计算缩放因子beta，使得缩放后的图像总像素数不超过max_pixels\n",
    "        beta = math.sqrt((height * width) / max_pixels)\n",
    "        # 重新计算调整后的高度，确保为28的整数倍\n",
    "        h_bar = math.floor(height / beta / 28) * 28\n",
    "        # 重新计算调整后的宽度，确保为28的整数倍\n",
    "        w_bar = math.floor(width / beta / 28) * 28\n",
    "    elif h_bar * w_bar < min_pixels:\n",
    "        # 计算缩放因子beta，使得缩放后的图像总像素数不低于min_pixels\n",
    "        beta = math.sqrt(min_pixels / (height * width))\n",
    "        # 重新计算调整后的高度，确保为28的整数倍\n",
    "        h_bar = math.ceil(height * beta / 28) * 28\n",
    "        # 重新计算调整后的宽度，确保为28的整数倍\n",
    "        w_bar = math.ceil(width * beta / 28) * 28\n",
    "    return h_bar, w_bar\n",
    "\n",
    "# 将test.png替换为本地的图像路径\n",
    "h_bar, w_bar = token_calculate(\"C:/Users/serap/Pictures/1.png\")\n",
    "print(f\"缩放后的图像尺寸为：高度为{h_bar}，宽度为{w_bar}\")\n",
    "\n",
    "# 计算图像的Token数：总像素除以28 * 28\n",
    "token = int((h_bar * w_bar) / (28 * 28))\n",
    "\n",
    "# 系统会自动添加<|vision_bos|>和<|vision_eos|>视觉标记（各计1个Token）\n",
    "print(f\"图像的Token数为{token + 2}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
